package com.lins.common.util;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ThreadPoolUtil {

	private static volatile ThreadPoolUtil instance;
	private ThreadPoolExecutor pool;
	
	public static ThreadPoolUtil getInstance() {
		if (instance == null) {
			synchronized(ThreadPoolUtil.class) {
				if (instance == null) {
					instance = new ThreadPoolUtil();
				}
			}
		}
		return instance;
	}
	
	//获取线程池快照信息
	public SystemThreadPoolVO getInfo() {
		SystemThreadPoolVO vo = new SystemThreadPoolVO();
		vo.setTaskNum(pool.getTaskCount());
		vo.setCompleteNum(pool.getCompletedTaskCount());
		vo.setMaxPoolSize(pool.getMaximumPoolSize());
		vo.setLagestPoolSize(pool.getLargestPoolSize());
		vo.setPoolSize(pool.getPoolSize());
		
		return vo;
	}
	
	/**
	 * 
	 * 添加线程
	 * 
	 * @param thread
	 *
	 * @变更记录 2017-2-23 下午12:13:26 李伟 创建
	 *
	 */
	public void run(Runnable thread) {
		pool.execute(thread);
	}

	public ThreadPoolUtil() {
		/** 
		 * 
	     * 线程池初始化方法 
	     *  
	     * corePoolSize 核心线程池大小
	     * maximumPoolSize 最大线程池大小
	     * keepAliveTime 线程池中超过corePoolSize数目的空闲线程最大存活时间
	     * TimeUnit keepAliveTime时间单位
	     * workQueue 阻塞队列
	     * threadFactory 新建线程工厂
	     * rejectedExecutionHandler 当提交任务数超过maxmumPoolSize+workQueue之和时, 
	     *                          任务会交给RejectedExecutionHandler来处理 
	     */ 
		pool = new ThreadPoolExecutor(  
			ConfigPropsUtil.getIntValue("thread.pool.core.size"), 
			ConfigPropsUtil.getIntValue("thread.pool.max.size"), 
			ConfigPropsUtil.getIntValue("thread.pool.max.keep.time"), 
			TimeUnit.MINUTES,  
	        new ArrayBlockingQueue<Runnable>(ConfigPropsUtil.getIntValue("thread.pool.block.size")),
	        new CustomRejectedExecutionHandler());
	}
	
    private class CustomRejectedExecutionHandler implements RejectedExecutionHandler {  
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {  
        	log.error("ThreadPoolUtil线程池阻塞队列已满！", new Exception("ThreadPoolUtil线程池阻塞队列已满！"));
        }  
    }
	
}
